/*
  作者: 劳兆城
  描述: 创建 所有业务图层 的方法
*/

import Vue from 'vue'
import Map from 'ol/map'
import View from 'ol/view'
import Interaction from 'ol/interaction'
import InteractionDraw from 'ol/interaction/draw'
import * as Url from './url'
import * as Layer from './layer'
import * as Source from './source'
import * as Feature from './feature'
import * as Common from './common'
import * as Module from './module'
import * as Geom from './geom'
import * as Format from './format'
import * as Interactions from './interaction'
import * as Control from './control'
import * as Util from './util'
import * as Style from './style'
import * as Modal from './modal'
import * as Tool from './tool'
import './scss/index.scss'

let modalZIndex = 100
const { ERR_OK, ARCGISICON_ERR_OK } = Util
const FsNhCenter = [113.0445, 23.0907]
const customTypeIconError = '自定义图标图层必须传入api路径（apiUrl字段）或者数据（data字段）'

// 基础数据图标图层通用方法
const ordinaryModal = {}
const ordinaryInfo = {}
const ordinaryLayer = (layerOptions, options = {}) => {
  const {
    layerKey,
    lngKey = 'lng',
    latKey = 'lat',
    titleKey = 'name',
    hideClassKey = '12',
    requestData = {}
  } = options

  if (ordinaryInfo[layerKey] === undefined) {
    ordinaryInfo[layerKey] = (res) => {
      const layerName = `${layerKey}Layer`

      if (res.code === ERR_OK) {
        const features = Feature.createFeaturesIcon({
          lngKey,
          latKey,
          data: res.result,
          img: require(`./img/${layerKey}.png`)
        })

        const layer = Layer.createLayerIcon({ layerName, features })

        const overLayerArr = []
        const hideClass = `GykjMap-isHide--${hideClassKey}`

        res.result.map(item => {
          const lng = item[lngKey]
          const lat = item[latKey]
          if (lng && lat) {
            let name = item[titleKey]

            if (name) {
              const htmlStr = `
                <div>
                  <span class="GykjMap-info-blue">${name}</span>
                </div>
              `

              const overLayer = Layer.createOverLayer({
                element: Common._createInfoBox(htmlStr, `GykjMap-${layerKey} ${hideClass}`),
                position: [lng, lat]
              })
              overLayerArr.push(overLayer)
            }
          }
        })

        const ModalConstructor = Vue.extend(Modal[layerKey])

        const showModal = (options) => {
          if (ordinaryModal[layerKey] === undefined) {
            ordinaryModal[layerKey] = new ModalConstructor()
            ordinaryModal[layerKey].vm = ordinaryModal[layerKey].$mount()
            document.body.appendChild(ordinaryModal[layerKey].vm.$el)
          }

          ordinaryModal[layerKey].vm.$el.style.zIndex = modalZIndex += 1
          ordinaryModal[layerKey].showModal(options)
        }

        return {
          code: res.code,
          layerName,
          layer,
          overLayerArr,
          hideClass,
          showModal
        }
      } else {
        return res
      }
    }
  }

  return Common._customData(layerOptions, {
    url: Url[`${layerKey}LayerUrl`],
    data: requestData,
    callback: ordinaryInfo[layerKey]
  })
}

const pipeLayer = (layerOptions, options) => {
  const { layerKey, strokeColor = '#7f00ff', strokeWidth = 3 } = options

  if (ordinaryInfo[layerKey] === undefined) {
    ordinaryInfo[layerKey] = (res) => {
      const layerName = `${layerKey}Layer`

      if (res.code === ERR_OK) {
        const arr = []
        res.result.map(item => {
          const obj = {
            geometry: {
              type: 'LineString',
              coordinates: JSON.parse(item.path)
            },
            properties: item,
            type: 'Feature'
          }
          arr.push(obj)
        })
        const geoJson = {
          features: arr,
          type: 'FeatureCollection'
        }
        const layer = Layer.createLayerVector({
          source: Source.createSourceVector({
            features: (Format.createFormatGeoJson()).readFeatures(geoJson, {
              dataProjection: 'EPSG:4326',
              featureProjection: 'EPSG:4326'
            })
          }),
          style: function (feature, resolution) {
            return Style.createStyle({
              stroke: Style.createStroke({
                color: strokeColor,
                width: strokeWidth
              })
            })
          },
          name: layerName
        })

        const ModalConstructor = Vue.extend(Modal[layerKey])

        const showModal = (options) => {
          if (ordinaryModal[layerKey] === undefined) {
            ordinaryModal[layerKey] = new ModalConstructor()
            ordinaryModal[layerKey].vm = ordinaryModal[layerKey].$mount()
            document.body.appendChild(ordinaryModal[layerKey].vm.$el)
          }

          ordinaryModal[layerKey].vm.$el.style.zIndex = modalZIndex += 1
          ordinaryModal[layerKey].showModal(options)
        }

        return {
          code: res.code,
          layerName,
          layer,
          showModal
        }
      } else {
        return res
      }
    }
  }

  return Common._customData(layerOptions, {
    url: Url[`${layerKey}LayerUrl`],
    data: {},
    callback: ordinaryInfo[layerKey]
  })
}

// 实例化创建地图
export const createMap = (options) => {
  if (typeof options !== 'object' || Array.isArray(options)) {
    Common._showError('你必须传入一个对象')
  }

  const {
    el,
    layers,
    viewOption,
    controls
  } = options

  return new Map({
    target: el,
    layers: layers,
    view: new View({
      center: FsNhCenter,
      zoom: 10,
      maxZoom: 19,
      minZoom: 5,
      projection: 'EPSG:4326',
      ...viewOption
    }),
    controls: controls || Control.createControl({
      attribution: false,
      zoom: false
    }),
    // 解决在移动端上地图可旋转的情况
    interactions: Interaction.defaults({ pinchRotate: false })
  })
}

// 白底地图图层
export const baseLayer = ({ sourceOptions, layerOptions } = {}) => {
  const source = Source.createSourceArcgis({
    ...sourceOptions,
    url: Url.baseLayerUrl
  })

  return Layer.createLayerTile({
    ...layerOptions,
    source
  })
}

// 地形图图层
export const terrainLayer = ({ sourceOptions, layerOptions } = {}) => {
  const source = Source.createSourceXYZ({
    ...sourceOptions,
    url: Url.terrainLayerUrl
  })

  return Layer.createLayerTile({
    ...layerOptions,
    source
  })
}

// 广东卫星图图层
export const GdSatelliteLayer = ({ sourceOptions, layerOptions } = {}) => {
  const source = Source.createSourceXYZ({
    minZoom: 0,
    maxZoom: 18,
    ...sourceOptions,
    url: Url.GdSatelliteLayerUrl
  })

  return Layer.createLayerTile({
    ...layerOptions,
    source
  })
}

// 佛山卫星图图层
export const FsSatelliteLayer = ({ sourceOptions, layerOptions } = {}) => {
  const source = Source.createSourceXYZ({
    minZoom: 0,
    maxZoom: 18,
    ...sourceOptions,
    url: Url.FsSatelliteLayerUrl
  })

  return Layer.createLayerTile({
    ...layerOptions,
    source
  })
}

// 佛山南海边框图层
export const FsNhBorderLayer = ({ sourceOptions, layerOptions } = {}) => {
  const source = Source.createSourceArcgis({
    ...sourceOptions,
    url: Url.FsNhBorderLayerUrl
  })

  return Layer.createLayerTile({
    ...layerOptions,
    source
  })
}

// 佛山南海镇街名图层
export const FsNhTownLayer = ({ sourceOptions, layerOptions } = {}) => {
  const source = Source.createSourceArcgis({
    ...sourceOptions,
    url: Url.FsNhTownLayerUrl
  })

  return Layer.createLayerTile({
    ...layerOptions,
    source
  })
}

// 警戒线图层
export const warnLineLayer = ({ layerOptions } = {}) => {
  const arr1 = [[127, 34], [127, 22], [119, 18], [119, 11], [113, 4.5], [105, 0]]
  const arr2 = [[132, 34], [132, 15], [120, 0], [105, 0]]

  const feature1 = Feature.createFeature({
    geometry: Geom.createLine(arr1)
  })

  feature1.setStyle(Style.createStyle({
    stroke: Style.createStroke({
      color: 'red',
      width: 1
    }),
    text: Style.createText({
      text: '24小时警戒线',
      font: '14px 微软雅黑',
      fill: Style.createFill({
        color: 'white'
      }),
      stroke: Style.createStroke({
        color: 'black',
        width: 2
      })
    })
  }))

  const feature2 = Feature.createFeature({
    geometry: Geom.createLine(arr2)
  })

  feature2.setStyle(Style.createStyle({
    stroke: Style.createStroke({
      color: 'green',
      width: 2,
      lineDash: [9]
    }),
    text: Style.createText({
      text: '48小时警戒线',
      font: '14px 微软雅黑',
      fill: Style.createFill({
        color: 'white'
      }),
      stroke: Style.createStroke({
        color: 'black',
        width: 2
      })
    })
  }))

  return Layer.createLayerVector({
    source: Source.createSourceVector({
      features: [feature1, feature2]
    }),
    name: 'warnLineLayer'
  })
}

// 广东水网
export const GdWaterNetLayer = ({ sourceOptions, layerOptions } = {}) => {
  const source = Source.createSourceArcgis({
    ...sourceOptions,
    url: Url.GdWaterNetLayerUrl
  })

  return Layer.createLayerTile({
    ...layerOptions,
    source
  })
}

// 华南水网
export const HnWaterNetLayer = ({ sourceOptions, layerOptions } = {}) => {
  const source = Source.createSourceArcgis({
    ...sourceOptions,
    url: Url.HnWaterNetLayerUrl
  })

  return Layer.createLayerTile({
    ...layerOptions,
    source
  })
}

// 路网
export const roadNetLayer = ({ sourceOptions, layerOptions } = {}) => {
  const source = Source.createSourceArcgis({
    ...sourceOptions,
    url: Url.roadNetLayerUrl
  })

  return Layer.createLayerTile({
    ...layerOptions,
    source
  })
}

// 气象预警
const weatherWarningInfo = (res) => {
  if (res.code === ERR_OK) {
    const overLayerArr = []
    const result = res.result

    if (result.length) {
      result.map(item => {
        let htmlStr = ''
        item.content.map(items => {
          const img = require(`./img/alerticons/${items.level}.png`)
          htmlStr += `
            <div class="GykjMap-weatherWarning-wrapper">
              <img src=${img} />
              <span>${items.description}</span>
            </div>
          `
        })

        const overLayer = Layer.createOverLayer({
          element: Common._createInfoBox(htmlStr, 'GykjMap-weatherWarning'),
          position: [item.lng, item.lat]
        })
        overLayerArr.push(overLayer)
      })
    } else {
      const img = require('./img/alerticons/no-alerm.gif')
      const htmlStr = `
        <div class="GykjMap-weatherWarning-wrapper">
          <img src=${img} />
          <span>无预警</span>
        </div>
      `

      const overLayer = Layer.createOverLayer({
        element: Common._createInfoBox(htmlStr, 'GykjMap-weatherWarning'),
        position: FsNhCenter
      })
      overLayerArr.push(overLayer)
    }

    return {
      code: res.code,
      layerName: 'weatherWarningLayer',
      data: res,
      overLayerArr
    }
  } else {
    return res
  }
}
export const weatherWarningLayer = ({ layerOptions }) => {
  return new Promise((resolve, reject) => {
    let requestUrl = ''
    let requestData = {}

    if (layerOptions.isCustom === true) {
      if (Array.isArray(layerOptions.data)) {
        resolve(weatherWarningInfo({
          code: ERR_OK,
          result: layerOptions.data
        }))
        return
      } else if (layerOptions.apiUrl) {
        requestUrl = layerOptions.apiUrl || ''
      } else {
        resolve({
          msg: customTypeIconError
        })
        return
      }
    } else {
      requestUrl = Url.weatherWarningLayerUrl
    }

    Common._ajaxGet(requestUrl, requestData)
      .then(res => {
        resolve(weatherWarningInfo(res))
      })
  })
}

// 台风路径风圈
function createRing (option) {
  let features = []

  let ringColor = {
    radius7_quad: {
      'bg-color': 'rgba(155, 219, 203, 0.4)',
      'border-color': '#24B43D',
      'text': '7级风圈'
    },
    radius10_quad: {
      'bg-color': 'rgba(244, 255, 151, 0.4)',
      'border-color': '#DCD024',
      'text': '10级风圈'
    },
    radius12_quad: {
      'bg-color': 'rgba(247, 179, 178, 0.4)',
      'border-color': '#E72A1D',
      'text': '12级风圈'
    }
  }

  for (let key in ringColor) {
    let wktformat = Format.createFormatWKT()
    let Configs = {
      CIRCLE_CENTER_X: option.longitude,
      CIRCLE_CENTER_Y: option.latitude,
      CIRCLE_R: {
        'SE': +option[key].se / 100 || 0,
        'NE': +option[key].ne / 100 || 0,
        'NW': +option[key].nw / 100 || 0,
        'SW': +option[key].sw / 100 || 0
      }
    }

    /* eslint-disable */
    if (
      Configs.CIRCLE_R.SE == 0 &&
      Configs.CIRCLE_R.NE == 0 &&
      Configs.CIRCLE_R.NW == 0 &&
      Configs.CIRCLE_R.SW == 0
    ) {
    /* eslint-enable */
      continue
    } else {
      let wkt = 'POLYGON(('
      let wkt0 = ''
      let _interval = 1
      for (let i = 0; i < 360 / _interval; i++) {
        let _r = 0
        let _ang = i * _interval
        if (_ang > 0 && _ang <= 90) {
          _r = Configs.CIRCLE_R.NE
        } else if (_ang > 90 && _ang <= 180) {
          _r = Configs.CIRCLE_R.NW
        } else if (_ang > 180 && _ang <= 270) {
          _r = Configs.CIRCLE_R.SW
        } else {
          _r = Configs.CIRCLE_R.SE
        }

        let x = Configs.CIRCLE_CENTER_X + _r * Math.cos(_ang * 3.14 / 180)
        let y = Configs.CIRCLE_CENTER_Y + _r * Math.sin(_ang * 3.14 / 180)

        wkt = wkt + '' + x + ' ' + y + ', '
        if (i === 0) {
          wkt0 = '' + x + ' ' + y + ''
        }
      }
      wkt = wkt + wkt0 + '))'
      let ringFeature = wktformat.readFeature(wkt)
      ringFeature.setStyle(Style.createStyle({
        fill: Style.createFill({
          color: ringColor[key]['bg-color']
        }),
        stroke: Style.createStroke({
          color: ringColor[key]['border-color'],
          width: 2
        })
      }))

      ringFeature.set('type', 'ring')
      features.push(ringFeature)
    }
  }

  return features
}

// 台风路径黑心点
function createTyphoonPoint (info, item) {
  let feature = Feature.createFeature(Geom.createPoint([+item.longitude, +item.latitude]))
  let strongIndex = Module.typhoonStrongLegend.findIndex(items => items.name === item.strong)

  feature.setStyle(Style.createStyle({
    image: Style.createCircle({
      fill: Style.createFill({
        color: Module.typhoonStrongLegend[strongIndex].color
      }),
      stroke: Style.createStroke({
        color: 'black',
        width: 2
      }),
      radius: 5
    }),
    zIndex: 10
  }))

  feature.set('type', 'point')
  feature.set('info', {
    typhoon_name: info.name,
    ...item
  })

  return feature
}

// 台风路径实线
function createTyphoonSolidLine (pointsArr) {
  let solidFeature = Feature.createFeature({
    geometry: Geom.createLine(pointsArr)
  })

  solidFeature.setStyle(Style.createStyle({
    stroke: Style.createStroke({
      color: 'black',
      width: 3,
      zIndex: 9
    })
  }))

  solidFeature.set('type', 'solidLine')

  return solidFeature
}

// 台风路径虚线
function createTyphoonDashLine (info, option) {
  let features = []

  if (option.forecast) {
    option.forecast.map(item => {
      // let points = item.points
      let localArr = []

      let ForecastIndex = Module.typhoonForecastLegend.findIndex(items => items.name === item.sets)

      if (ForecastIndex >= 0) {
        let color = Module.typhoonForecastLegend[ForecastIndex].color
        let pointColor = Module.typhoonForecastLegend[ForecastIndex].pointColor

        localArr.push([+option.longitude, +option.latitude])

        item.points.map(items => {
          let local = [+items.longitude, +items.latitude]

          localArr.push(local)

          let feature = Feature.createFeature(Geom.createPoint(local))

          feature.setStyle(Style.createStyle({
            image: Style.createCircle({
              fill: Style.createFill({
                color: pointColor
              }),
              stroke: Style.createStroke({
                color: 'black',
                width: 2
              }),
              radius: 5
            }),
            zIndex: 10
          }))

          feature.set('type', 'dashPoint')
          feature.set('info', {
            tfbh: option.tfbh,
            typhoon_name: info.name,
            sets: item.sets,
            ...items
          })
          features.push(feature)
        })

        let feature = Feature.createFeature({
          geometry: Geom.createLine(localArr)
        })

        feature.setStyle(Style.createStyle({
          stroke: Style.createStroke({
            color: color,
            width: 2,
            lineDash: [9]
          })
        }))

        feature.set('type', 'dashLine')
        features.push(feature)
      }
    })
  }

  return features
}

// 台风路径强度图标
function createTyphoonStrong (option) {
  let el = Common._createHtml('div')
  let strongIndex = Module.typhoonStrongLegend.findIndex(item => item.name === option.strong)
  el.className = 'GykjMap-typhoon-ringCenter'
  let imgPosition = Module.typhoonStrongLegend[strongIndex].imgPosition
  el.style.backgroundPosition = imgPosition

  let overLayer = Layer.createOverLayer({
    element: el,
    position: [option.longitude, option.latitude]
  })

  return overLayer
}

// 台风路径信息框
export function createTyphoonContent (obj) {
  let title = obj.title
  let content = obj.content
  let local = obj.local

  let el = Common._createHtml('div')
  el.className = 'GykjMap-typhoonInfo pad-10'

  let warp = Common._createHtml('div')
  warp.className = 'warpper'

  let headerWarp = Common._createHtml('header')
  headerWarp.className = 'header'
  headerWarp.innerHTML = `
    <div class="title">${title}</div>
    <div class="GykjMap-typhoonInfo-close">&times;</div>
  `

  let contentWarp = Common._createHtml('div')
  contentWarp.className = 'content'
  contentWarp.innerHTML = content

  warp.append(headerWarp)
  warp.append(contentWarp)

  let tail = Common._createHtml('div')
  tail.className = 'tail'
  tail.innerHTML = '<span class="iconfont icon-zelvxuanzefeiyongdaosanjiaoxingfandui"></span>'

  el.append(warp)
  el.append(tail)

  let overLayer = Layer.createOverLayer({
    element: el,
    position: [local[0], local[1]]
  })

  return overLayer
}

// 整个台风
export function createTyphoon (info) {
  let option = info.points[0]
  // let optionEnd = info.points[info.points.length - 1]
  let options = info.points
  let arr = []
  let obj = {}

  let dashLine = createTyphoonDashLine(info, option)
  let strong = createTyphoonStrong(option)

  for (let i = options.length - 1; i >= 0; i--) {
    let rings = createRing(options[i])
    let point = createTyphoonPoint(info, options[i])
    let solidLine

    if (i < options.length - 1) {
      let local = [+options[i].longitude, +options[i].latitude]
      let localNext = [+options[i + 1].longitude, +options[i + 1].latitude]

      solidLine = createTyphoonSolidLine([local, localNext])
    }

    arr.push({
      rings,
      point,
      solidLine
    })
  }

  obj['typhoonIng'] = arr
  if (dashLine) {
    obj['typhoonWill'] = dashLine
  }
  obj['typhoonStrong'] = strong
  obj['typhoonStartInfo'] = option

  let layers = {}
  const tfbh = option.tfbh

  layers[tfbh] = {}

  layers[tfbh]['layer'] = Layer.createLayerVector({
    source: Source.createSourceVector({
      features: []
    }),
    name: 'typhoonLayer',
    zIndex: 12
  })

  layers[tfbh]['typhoon'] = obj

  return layers
}

let typhoonModal = null
const typhoonInfo = (res, layerOptions) => {
  const layerName = 'typhoonLayer'

  if (res.code === ERR_OK) {
    let isHaveTyphoon = false
    let layers = {}
    let result = []

    if (res.result.length) {
      result = res.result

      res.result.map(item => {
        layers = {
          ...layers,
          ...createTyphoon(item)
        }
      })

      isHaveTyphoon = true
    }

    const LayerConstructor = Vue.extend(Tool.typhoon)

    typhoonModal = new LayerConstructor({
      propsData: {
        Map: layerOptions.Map,
        layers: layerOptions.Layers
      }
    })

    typhoonModal.vm = typhoonModal.$mount()
    layerOptions.Dom.appendChild(typhoonModal.vm.$el)

    typhoonModal.getList()

    const showModal = (options) => {
      const featureType = options.get('type')
      const featureInfo = options.get('info')

      if (featureType === 'point' || featureType === 'dashPoint') {
        typhoonModal.showTyphoonInfoLayer(featureType, featureInfo)
      }
    }

    const response = {
      code: res.code,
      layerName,
      layers,
      result,
      isHaveTyphoon,
      animateData: {
        zoom: 4,
        center: [117.43903125000003, 14.345582812500005]
      },
      showModal,
      hideInfo () {
        typhoonModal.removeData()
      }
    }

    typhoonModal.initData({ ...response }, layerOptions)

    return response
  } else {
    return res
  }
}
// 台风路径
export const typhoonLayer = ({ layerOptions }) => {
  return Common._customData(layerOptions, {
    url: Url.typhoonLayerUrl,
    data: {},
    callback: (res) => {
      return typhoonInfo(res, layerOptions)
    }
  })
}

// 台风历史列表
export const getTyphoonList = () => {
  return Common._ajaxGet(Url.typhoonListUrl, {})
}

// 单个台风路径
export const getTyphoonSingelInfo = (tfbh) => {
  return Common._ajaxGet(Url.typhoonInfpUrl, { tfbh })
}

const cloudRadarInterval = (options = {}) => {
  const { layer, data, extent } = options
  const result = data.result
  let index = result.length - 1

  if (options['timeInterval']) {
    clearInterval(options['timeInterval'])
  }

  options['timeInterval'] = setInterval(() => {
    options['dateTime'] = result[index].datatime
    layer.setSource(Source.createSourceImage({
      url: result[index].imageurl,
      imageExtent: extent
    }))
    index--
    if (index === -1) {
      clearInterval(options['timeInterval'])
    }
  }, 500)
}

let cloudRadarModal = null
const cloudInfo = (res, layerOptions) => {
  if (res.code === ERR_OK) {
    let layer = null
    let dateTime = null
    const extent = [50, 0, 145, 60]

    if (res.result.length) {
      const info = res.result[res.result.length - 1]
      dateTime = info.datatime
      layer = Layer.createLayerImage({
        source: Source.createSourceImage({
          url: info.imageurl,
          imageExtent: extent
        }),
        opacity: 0.8
      })
    }

    if (cloudRadarModal === null) {
      const LayerConstructor = Vue.extend(Tool.cloudRadar)

      cloudRadarModal = new LayerConstructor({
        propsData: {
          Map: layerOptions.Map,
          layers: layerOptions.Layers
        }
      })

      cloudRadarModal.vm = cloudRadarModal.$mount()
      layerOptions.Dom.appendChild(cloudRadarModal.vm.$el)
    }

    const layerName = 'cloudLayer'

    const response = {
      code: res.code,
      layerName,
      data: res,
      layer: layer,
      extent: extent,
      interval: cloudRadarInterval,
      dateTime: dateTime,
      animateData: {
        zoom: 5,
        center: [113.47418750000003, 22.73913750000002]
      },
      refreshAnimate () {
        cloudRadarModal.refreshAnimate({ layerName })
      }
    }

    cloudRadarModal.initData(response, layerOptions)

    return response
  } else {
    return res
  }
}
// 云图
export const cloudLayer = ({ layerOptions }) => {
  return Common._customData(layerOptions, {
    url: Url.cloudLayerUrl,
    data: { imageType: 'cloudImage' },
    callback: (res) => {
      return cloudInfo(res, layerOptions)
    }
  })
}

const radarInfo = (res, layerOptions) => {
  if (res.code === ERR_OK) {
    let layer = null
    let dateTime = null
    const extent = [73, 15.5, 135.5, 55.5]

    if (res.result.length) {
      const info = res.result[res.result.length - 1]
      dateTime = info.datatime
      layer = Layer.createLayerImage({
        source: Source.createSourceImage({
          url: info.imageurl,
          imageExtent: extent
        }),
        opacity: 0.8
      })
    }

    if (cloudRadarModal === null) {
      const LayerConstructor = Vue.extend(Tool.cloudRadar)

      cloudRadarModal = new LayerConstructor({
        propsData: {
          Map: layerOptions.Map,
          layers: layerOptions.Layers
        }
      })

      cloudRadarModal.vm = cloudRadarModal.$mount()
      layerOptions.Dom.appendChild(cloudRadarModal.vm.$el)
    }

    const layerName = 'radarLayer'

    const response = {
      code: res.code,
      layerName,
      data: res,
      layer: layer,
      extent: extent,
      interval: cloudRadarInterval,
      dateTime: dateTime,
      animateData: {
        zoom: 5,
        center: [113.47418750000003, 22.73913750000002]
      },
      refreshAnimate () {
        cloudRadarModal.refreshAnimate({ layerName })
      }
    }

    cloudRadarModal.initData(response, layerOptions)

    return response
  } else {
    return res
  }
}
// 雷达
export const radarLayer = ({ layerOptions }) => {
  return Common._customData(layerOptions, {
    url: Url.cloudLayerUrl,
    data: { imageType: 'radarImage' },
    callback: (res) => {
      return radarInfo(res, layerOptions)
    }
  })
}

let currentZoom = 10
const getMapSize = (layerOptions, mode) => {
  let isRefresh = false
  const { Map } = layerOptions
  const MapView = Map.getView()
  const center = MapView.getCenter()
  const zoom = parseInt(MapView.getZoom())

  if (zoom !== currentZoom) {
    currentZoom = zoom
    isRefresh = true
  }

  return {
    isRefresh,
    mode,
    zoom: currentZoom,
    x: center[0],
    y: center[1]
  }
}
const arcgisIconLayer = (layerOptions, options = {}) => {
  const {
    layerKey,
    mode = '排水口',
    lngKey = 'lng',
    latKey = 'lat'
  } = options

  if (ordinaryInfo[layerKey] === undefined) {
    ordinaryInfo[layerKey] = (res) => {
      const layerName = `${layerKey}Layer`

      if (res.code === ARCGISICON_ERR_OK || res.code === ERR_OK) {
        const features = Feature.createFeaturesIcon({
          lngKey,
          latKey,
          data: res.contents || res.result,
          img: require(`./img/${layerKey}.png`)
        })

        const layer = Layer.createLayerIcon({ layerName, features })

        const ModalConstructor = Vue.extend(Modal[layerKey])

        const showModal = (options) => {
          if (ordinaryModal[layerKey] === undefined) {
            ordinaryModal[layerKey] = new ModalConstructor()
            ordinaryModal[layerKey].vm = ordinaryModal[layerKey].$mount()
            document.body.appendChild(ordinaryModal[layerKey].vm.$el)
          }

          ordinaryModal[layerKey].vm.$el.style.zIndex = modalZIndex += 1
          ordinaryModal[layerKey].showModal(options)
        }

        const changeSize = (layer) => {
          if (layerOptions.isCustom) {
            return
          }

          const requestData = getMapSize(layerOptions, mode)

          if (!requestData.isRefresh) {
            return
          } else {
            delete requestData.isRefresh
          }

          Common._ajaxGet(Url[`${layerKey}LayerUrl`], requestData)
            .then(res => {
              if (res.code === ARCGISICON_ERR_OK) {
                const features = Feature.createFeaturesIcon({
                  lngKey,
                  latKey,
                  data: res.contents,
                  img: require(`./img/${layerKey}.png`)
                })
                layer.setSource(Source.createSourceVector({ features }))
              }
            })
        }

        return {
          code: ERR_OK,
          layerName,
          layer,
          showModal,
          changeSize
        }
      } else {
        return res
      }
    }
  }

  const requestData = getMapSize(layerOptions, mode)
  delete requestData.isRefresh

  return Common._customData(layerOptions, {
    url: Url[`${layerKey}LayerUrl`],
    data: requestData,
    callback: ordinaryInfo[layerKey]
  })
}

// 排水口
export const drainPortLayer = ({ layerOptions }) => {
  return arcgisIconLayer(layerOptions, {
    layerKey: 'drainPort',
    mode: '排水口'
  })
}

// 堤围
let banksModal = null
export const banksLayer = ({ layerOptions }) => {
  const layerName = 'banksLayer'
  const layer = Layer.createLayerKml({
    url: layerOptions.apiUrl || Url.banksLayerUrl,
    name: layerName
  })

  const ModalConstructor = Vue.extend(Modal.banks)

  const showModal = (options) => {
    if (banksModal === null) {
      banksModal = new ModalConstructor()
      banksModal.vm = banksModal.$mount()
      document.body.appendChild(banksModal.vm.$el)
    }

    banksModal.vm.$el.style.zIndex = modalZIndex += 1
    banksModal.showModal(options)
  }

  return {
    layer,
    layerName,
    showModal
  }
}

// 险段
let criticalsModal = null
export const criticalsLayer = ({ layerOptions }) => {
  const layerName = 'criticalsLayer'
  const layer = Layer.createLayerKml({
    url: layerOptions.apiUrl || Url.criticalsLayerUrl,
    name: layerName
  })

  const ModalConstructor = Vue.extend(Modal.criticals)

  const showModal = (options) => {
    if (criticalsModal === null) {
      criticalsModal = new ModalConstructor()
      criticalsModal.vm = criticalsModal.$mount()
      document.body.appendChild(criticalsModal.vm.$el)
    }

    criticalsModal.vm.$el.style.zIndex = modalZIndex += 1
    criticalsModal.showModal(options)
  }

  return {
    layer,
    layerName,
    showModal
  }
}

// 堤上在建工程
export const dikeEngineeringLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'dikeEngineering',
    titleKey: '工程名称'
  })
}

// 水闸
let gateModal = null
const gateInfo = (res) => {
  const layerName = 'gateLayer'

  if (res.code === ERR_OK) {
    const overLayerArr = []
    const features = []
    const hideClass = 'GykjMap-isHide--15'
    const realDataImg = require('./img/gate.png')
    const realNoDataImg = require('./img/gate2.png')

    res.result.map(item => {
      const lng = item.stalong
      const lat = item.stalat
      if (lng && lat) {
        features.push(
          Feature.createFeatureIcon({
            lng,
            lat,
            data: item,
            img: Common._isWaterRealdata(item) ? realDataImg : realNoDataImg
          })
        )

        const time = item.realtime_data ? item.realtime_data.data_time ? item.realtime_data.data_time : '--' : '--'
        const status = item.realtime_data ? item.realtime_data.outertrend ? item.realtime_data.outertrend : '' : ''
        const levelIn = item.realtime_data ? item.realtime_data.water_river_in || item.realtime_data.water_level === 0 ? item.realtime_data.water_river_in : '--' : '--'
        const levelOut = item.realtime_data ? item.realtime_data.water_river_out || item.realtime_data.water_level === 0 ? item.realtime_data.water_river_out : '--' : '--'

        const htmlStr = `
          <div>
            <span class="GykjMap-info-red">${time}</span>
          </div>
          <div>
            <span class="GykjMap-info-blue">${item.sluicegate_name}</span>
            内江：
            <span class="GykjMap-info-blue">${levelIn}</span> 米;
            外江：
            <span class="GykjMap-info-blue">${levelOut}</span> 米
            ${Common._waterOutertrend(status)}
          </div>
        `

        overLayerArr.push(
          Layer.createOverLayer({
            element: Common._createInfoBox(htmlStr, `GykjMap-waterLevel ${hideClass}`),
            position: [lng, lat]
          })
        )
      }
    })

    const layer = Layer.createLayerIcon({ layerName, features })

    const ModalConstructor = Vue.extend(Modal.gate)

    const showModal = (options) => {
      if (gateModal === null) {
        gateModal = new ModalConstructor()
        gateModal.vm = gateModal.$mount()
        document.body.appendChild(gateModal.vm.$el)
      }

      gateModal.vm.$el.style.zIndex = modalZIndex += 1
      gateModal.showModal(options)
    }

    return {
      code: res.code,
      layerName,
      layer,
      overLayerArr,
      hideClass,
      showModal
    }
  } else {
    return res
  }
}
export const gateLayer = ({ layerOptions }) => {
  return Common._customData(layerOptions, {
    url: Url.gateLayerUrl,
    data: { sttype: '水闸' },
    callback: gateInfo
  })
}

// 泵站
let pumpModal = null
const pumpInfo = (res) => {
  const layerName = 'pumpLayer'

  if (res.code === ERR_OK) {
    const overLayerArr = []
    const features = []
    const hideClass = 'GykjMap-isHide--15'
    const realDataImg = require('./img/pump.png')
    const realNoDataImg = require('./img/pump2.png')

    res.result.map(item => {
      const lng = item.lng
      const lat = item.lat
      if (lng && lat) {
        features.push(
          Feature.createFeatureIcon({
            lng,
            lat,
            data: item,
            img: Common._isWaterRealdata(item) ? realDataImg : realNoDataImg
          })
        )

        const time = item.realtime_data ? item.realtime_data.data_time ? item.realtime_data.data_time : '--' : '--'
        const status = item.realtime_data ? item.realtime_data.outertrend ? item.realtime_data.outertrend : '' : ''
        const levelIn = item.realtime_data ? item.realtime_data.water_river_in || item.realtime_data.water_level === 0 ? item.realtime_data.water_river_in : '--' : '--'
        const levelOut = item.realtime_data ? item.realtime_data.water_river_out || item.realtime_data.water_level === 0 ? item.realtime_data.water_river_out : '--' : '--'

        const htmlStr = `
          <div>
            <span class="GykjMap-info-red">${time}</span>
          </div>
          <div>
            <span class="GykjMap-info-blue">${item.station_name}</span>
            内江：
            <span class="GykjMap-info-blue">${levelIn}</span> 米;
            外江：
            <span class="GykjMap-info-blue">${levelOut}</span> 米
            ${Common._waterOutertrend(status)}
          </div>
        `

        overLayerArr.push(
          Layer.createOverLayer({
            element: Common._createInfoBox(htmlStr, `GykjMap-waterLevel ${hideClass}`),
            position: [lng, lat]
          })
        )
      }
    })

    const layer = Layer.createLayerIcon({ layerName, features })

    const ModalConstructor = Vue.extend(Modal.pump)

    const showModal = (options) => {
      if (pumpModal === null) {
        pumpModal = new ModalConstructor()
        pumpModal.vm = pumpModal.$mount()
        document.body.appendChild(pumpModal.vm.$el)
      }

      pumpModal.vm.$el.style.zIndex = modalZIndex += 1
      pumpModal.showModal(options)
    }

    return {
      code: res.code,
      layerName,
      layer,
      overLayerArr,
      hideClass,
      showModal
    }
  } else {
    return res
  }
}
export const pumpLayer = ({ layerOptions }) => {
  return Common._customData(layerOptions, {
    url: Url.pumpLayerUrl,
    data: { sttype: '泵站' },
    callback: pumpInfo
  })
}

// 水位站
let waterLevelModal = null
const waterLevelInfo = (res) => {
  const layerName = 'waterLevelLayer'

  if (res.code === ERR_OK) {
    const overLayerArr = []
    const features = []
    const realDataImg = require('./img/waterLevel.png')
    const realNoDataImg = require('./img/waterLevel2.png')

    res.result.map(item => {
      const lng = item.lng
      const lat = item.lat
      if (lng && lat) {
        features.push(
          Feature.createFeatureIcon({
            lng,
            lat,
            data: item,
            img: Common._isWaterRealdata(item) ? realDataImg : realNoDataImg
          })
        )

        const name = item.stn_name
        const time = item.realtime_data ? item.realtime_data.data_time ? item.realtime_data.data_time : '--' : '--'
        const level = item.realtime_data ? item.realtime_data.water_level || item.realtime_data.water_level === 0 ? item.realtime_data.water_level : '--' : '--'
        const warn = item.realtime_data ? item.realtime_data.alarm_l1 || item.realtime_data.alarm_l1 === '-' ? item.realtime_data.alarm_l1 : false : false
        const warnImg = warn ? `<img class="GykjMap-waterLevel-warnImg" src=${Common._waterLevelWarn(item.realtime_data.trend, item.realtime_data.alarm_l1, item.realtime_data.waterlevel)} />` : ''

        const htmlStr = `
          <div>
            <span class="GykjMap-info-red">${time}</span>
          </div>
          <div>
            <span class="GykjMap-info-blue">${name}</span>
            水位：
            <span class="GykjMap-info-blue">${level}</span> 米
            ${warnImg}
          </div>
        `

        overLayerArr.push(
          Layer.createOverLayer({
            element: Common._createInfoBox(htmlStr, `GykjMap-waterLevel`),
            position: [lng, lat]
          })
        )
      }
    })

    const layer = Layer.createLayerIcon({ layerName, features })

    const ModalConstructor = Vue.extend(Modal.waterLevel)

    const showModal = (options) => {
      if (waterLevelModal === null) {
        waterLevelModal = new ModalConstructor()
        waterLevelModal.vm = waterLevelModal.$mount()
        document.body.appendChild(waterLevelModal.vm.$el)
      }

      waterLevelModal.vm.$el.style.zIndex = modalZIndex += 1
      waterLevelModal.showModal(options)
    }

    return {
      code: res.code,
      layerName,
      layer,
      overLayerArr,
      showModal
    }
  } else {
    return res
  }
}
export const waterLevelLayer = ({ layerOptions }) => {
  return Common._customData(layerOptions, {
    url: Url.waterLevelLayerUrl,
    data: { sttype: '水位站' },
    callback: waterLevelInfo
  })
}

// 水文站
let hydrologyModal = null
const hydrologyInfo = (res) => {
  const layerName = 'hydrologyLayer'

  if (res.code === ERR_OK) {
    const overLayerArr = []
    const features = []
    const realDataImg = require('./img/hydrology.png')
    const realNoDataImg = require('./img/hydrology2.png')

    res.result.map(item => {
      const lng = item.lng
      const lat = item.lat
      if (lng && lat) {
        features.push(
          Feature.createFeatureIcon({
            lng,
            lat,
            data: item,
            img: Common._isWaterRealdata(item) ? realDataImg : realNoDataImg
          })
        )

        const name = item.stn_name
        const time = item.realtime_data ? item.realtime_data.data_time ? item.realtime_data.data_time : '--' : '--'
        const level = item.realtime_data ? item.realtime_data.water_level || item.realtime_data.water_level === 0 ? item.realtime_data.water_level : '--' : '--'
        const warn = item.realtime_data ? item.realtime_data.alarm_l1 || item.realtime_data.alarm_l1 === '-' ? item.realtime_data.alarm_l1 : false : false
        const warnImg = warn ? `<img class="GykjMap-hydrology-warnImg" src=${Common._waterLevelWarn(item.realtime_data.trend, item.realtime_data.alarm_l1, item.realtime_data.waterlevel)} />` : ''

        const htmlStr = `
          <div>
            <span class="GykjMap-info-red">${time}</span>
          </div>
          <div>
            <span class="GykjMap-info-blue">${name}</span>
            水位：
            <span class="GykjMap-info-blue">${level}</span> 米
            ${warnImg}
          </div>
        `

        overLayerArr.push(
          Layer.createOverLayer({
            element: Common._createInfoBox(htmlStr, `GykjMap-hydrology`),
            position: [lng, lat]
          })
        )
      }
    })

    const layer = Layer.createLayerIcon({ layerName, features })

    const ModalConstructor = Vue.extend(Modal.hydrology)

    const showModal = (options) => {
      if (hydrologyModal === null) {
        hydrologyModal = new ModalConstructor()
        hydrologyModal.vm = hydrologyModal.$mount()
        document.body.appendChild(hydrologyModal.vm.$el)
      }

      hydrologyModal.vm.$el.style.zIndex = modalZIndex += 1
      hydrologyModal.showModal(options)
    }

    return {
      code: res.code,
      layerName,
      layer,
      overLayerArr,
      showModal
    }
  } else {
    return res
  }
}
export const hydrologyLayer = ({ layerOptions }) => {
  return Common._customData(layerOptions, {
    url: Url.hydrologyLayerUrl,
    data: { sttype: '水文站' },
    callback: hydrologyInfo
  })
}

// 潮位站
let tideGaugeModal = null
const tideGaugeInfo = (res) => {
  const layerName = 'tideGaugeLayer'

  if (res.code === ERR_OK) {
    const overLayerArr = []
    const features = []
    const realDataImg = require('./img/tideGauge.png')
    const realNoDataImg = require('./img/tideGauge2.png')

    res.result.map(item => {
      const lng = item.lng
      const lat = item.lat
      if (lng && lat) {
        features.push(
          Feature.createFeatureIcon({
            lng,
            lat,
            data: item,
            img: Common._isWaterRealdata(item) ? realDataImg : realNoDataImg
          })
        )

        const name = item.stn_name
        const time = item.realtime_data ? item.realtime_data.data_time ? item.realtime_data.data_time : '--' : '--'
        const level = item.realtime_data ? item.realtime_data.water_level || item.realtime_data.water_level === 0 ? item.realtime_data.water_level : '--' : '--'
        const warn = item.realtime_data ? item.realtime_data.alarm_l1 || item.realtime_data.alarm_l1 === '-' ? item.realtime_data.alarm_l1 : false : false
        const warnImg = warn ? `<img class="GykjMap-tideGauge-warnImg" src=${Common._waterLevelWarn(item.realtime_data.trend, item.realtime_data.alarm_l1, item.realtime_data.waterlevel)} />` : ''

        const htmlStr = `
          <div>
            <span class="GykjMap-info-red">${time}</span>
          </div>
          <div>
            <span class="GykjMap-info-blue">${name}</span>
            水位：
            <span class="GykjMap-info-blue">${level}</span> 米
            ${warnImg}
          </div>
        `

        overLayerArr.push(
          Layer.createOverLayer({
            element: Common._createInfoBox(htmlStr, `GykjMap-tideGauge`),
            position: [lng, lat]
          })
        )
      }
    })

    const layer = Layer.createLayerIcon({ layerName, features })

    const ModalConstructor = Vue.extend(Modal.tideGauge)

    const showModal = (options) => {
      if (tideGaugeModal === null) {
        tideGaugeModal = new ModalConstructor()
        tideGaugeModal.vm = tideGaugeModal.$mount()
        document.body.appendChild(tideGaugeModal.vm.$el)
      }

      tideGaugeModal.vm.$el.style.zIndex = modalZIndex += 1
      tideGaugeModal.showModal(options)
    }

    return {
      code: res.code,
      layerName,
      layer,
      overLayerArr,
      showModal
    }
  } else {
    return res
  }
}
export const tideGaugeLayer = ({ layerOptions }) => {
  return Common._customData(layerOptions, {
    url: Url.tideGaugeLayerUrl,
    data: { sttype: '潮位站' },
    callback: tideGaugeInfo
  })
}

// 江心洲
export const midRiverLandLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'midRiverLand',
    titleKey: '名称'
  })
}

// 外滩地
export const theBundLandLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'theBundLand',
    titleKey: '名称'
  })
}

// 水库
let reservoirModal = null
const reservoirInfo = (res) => {
  const layerName = 'reservoirLayer'

  if (res.code === ERR_OK) {
    const overLayerArr = []
    const features = []
    const hideClass = 'GykjMap-isHide--15'
    const realDataImg = require('./img/reservoir.png')
    const realNoDataImg = require('./img/reservoir2.png')

    res.result.map(item => {
      const lng = item.lng
      const lat = item.lat
      if (lng && lat) {
        features.push(
          Feature.createFeatureIcon({
            lng,
            lat,
            data: item,
            img: Common._isWaterRealdata(item) ? realDataImg : realNoDataImg
          })
        )

        const name = item.pool_name
        const time = item.realtime_data ? item.realtime_data.data_time ? item.realtime_data.data_time : '--' : '--'
        const level = item.realtime_data ? item.realtime_data.water_level || item.realtime_data.water_level === 0 ? item.realtime_data.water_level : '--' : '--'

        const htmlStr = `
          <div>
            <span class="GykjMap-info-red">${time}</span>
          </div>
          <div>
            <span class="GykjMap-info-blue">${name}</span>
            水位：
            <span class="GykjMap-info-blue">${level}</span> 米
          </div>
        `

        overLayerArr.push(
          Layer.createOverLayer({
            element: Common._createInfoBox(htmlStr, `GykjMap-reservoir ${hideClass}`),
            position: [lng, lat]
          })
        )
      }
    })

    const layer = Layer.createLayerIcon({ layerName, features })

    const ModalConstructor = Vue.extend(Modal.reservoir)

    const showModal = (options) => {
      if (reservoirModal === null) {
        reservoirModal = new ModalConstructor()
        reservoirModal.vm = reservoirModal.$mount()
        document.body.appendChild(reservoirModal.vm.$el)
      }

      reservoirModal.vm.$el.style.zIndex = modalZIndex += 1
      reservoirModal.showModal(options)
    }

    return {
      code: res.code,
      layerName,
      layer,
      overLayerArr,
      hideClass,
      showModal
    }
  } else {
    return res
  }
}
export const reservoirLayer = ({ layerOptions }) => {
  return Common._customData(layerOptions, {
    url: Url.reservoirLayerUrl,
    data: {},
    callback: reservoirInfo
  })
}

// 山塘
export const mountainPondLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'mountainPond',
    hideClassKey: '15',
    titleKey: '名称'
  })
}

// 城市内涝
let waterLoggingCityModal = null
const waterLoggingCityInfo = (res) => {
  const layerName = 'waterLoggingCityLayer'

  if (res.code === ERR_OK) {
    const overLayerArr = []
    const features = []
    const hideClass = 'GykjMap-isHide--14'
    const realDataImg = require('./img/waterloggingCity.png')
    const realNoDataImg = require('./img/waterloggingCity2.png')

    res.result.map(item => {
      const lng = item.lng
      const lat = item.lat
      if (lng && lat) {
        features.push(
          Feature.createFeatureIcon({
            lng,
            lat,
            data: item,
            img: Common._isWaterRealdata(item) ? realDataImg : realNoDataImg,
            changeWGS: 'gaode'
          })
        )

        const name = item.stn_name
        const time = item.realtime_data ? item.realtime_data.data_time ? item.realtime_data.data_time : '--' : '--'
        const level = item.realtime_data ? item.realtime_data.water_level || item.realtime_data.water_level === 0 ? item.realtime_data.water_level : '--' : '--'
        const warn = item.realtime_data ? item.realtime_data.alarm_l1 || item.realtime_data.alarm_l1 === '-' ? item.realtime_data.alarm_l1 : false : false
        const warnImg = warn ? `<img class="GykjMap-waterLoggingCity-warnImg" src=${Common._waterLevelWarn(item.realtime_data.trend, item.realtime_data.alarm_l1, item.realtime_data.waterlevel)} />` : ''

        const htmlStr = `
          <div>
            <span class="GykjMap-info-red">${time}</span>
          </div>
          <div>
            <span class="GykjMap-info-blue">${name}</span>
            水深：
            <span class="GykjMap-info-blue">${level}</span> 米
            ${warnImg}
          </div>
        `

        overLayerArr.push(
          Layer.createOverLayer({
            element: Common._createInfoBox(htmlStr, `GykjMap-waterLoggingCity ${hideClass}`),
            position: Util.gaodeChangeWgs([lng, lat])
          })
        )
      }
    })

    const layer = Layer.createLayerIcon({ layerName, features })

    const ModalConstructor = Vue.extend(Modal.waterLoggingCity)

    const showModal = (options) => {
      if (waterLoggingCityModal === null) {
        waterLoggingCityModal = new ModalConstructor()
        waterLoggingCityModal.vm = waterLoggingCityModal.$mount()
        document.body.appendChild(waterLoggingCityModal.vm.$el)
      }

      waterLoggingCityModal.vm.$el.style.zIndex = modalZIndex += 1
      waterLoggingCityModal.showModal(options)
    }

    return {
      code: res.code,
      layerName,
      layer,
      overLayerArr,
      hideClass,
      showModal
    }
  } else {
    return res
  }
}
export const waterLoggingCityLayer = ({ layerOptions }) => {
  return Common._customData(layerOptions, {
    url: Url.waterLoggingLayerUrl,
    data: { sttype: '内涝站' },
    callback: waterLoggingCityInfo
  })
}

// 通信设施(电信)
export const operatorTelecomLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'operatorTelecom',
    requestData: { type: '电信' }
  })
}

// 通信设施(联通)
export const operatorUnicomLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'operatorUnicom',
    requestData: { type: '联通' }
  })
}

// 通信设施(移动)
export const operatorMoveLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'operatorMove',
    requestData: { type: '移动' }
  })
}

// 通信设施(铁塔)
export const operatorTowerLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'operatorTower',
    requestData: { type: '铁塔公司' }
  })
}

// 旅游景点
export const tourismLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'tourism'
  })
}

// 危险化学品重点企业
export const dangerousGoodsLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'dangerousGoods',
    titleKey: 'company_name'
  })
}

// 重要电力设施
export const powerFacilitiesLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'powerFacilities',
    titleKey: '名称'
  })
}

// 学校
export const schoolLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'school'
  })
}

// 地质灾害
export const hazardLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'hazard',
    hideClassKey: '15',
    titleKey: 'code'
  })
}

// 穿堤管道(输气)
export const dikePipeGasLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'dikePipeGas',
    titleKey: '穿堤管道名称'
  })
}

// 内涝灾害(地下停车场)
export const waterloggingCarLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'waterloggingCar',
    titleKey: '名称'
  })
}

// 城建建筑工地
export const cityConstructionSiteLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'cityConstructionSite',
    hideClassKey: '15',
    titleKey: '工程名称',
    requestData: { type: '城建' }
  })
}

// 市政建筑工地
export const municipalConstructionSiteLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'municipalConstructionSite',
    titleKey: '工程名称',
    requestData: { type: '市政' }
  })
}

// 码头
export const wharfLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'wharf',
    titleKey: '码头名称'
  })
}

// 桥梁
export const bridgeLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'bridge',
    titleKey: '桥梁名称'
  })
}

// 内涝灾害(隧道)
export const waterloggingTunnelLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'waterloggingTunnel',
    titleKey: '名称'
  })
}

// 建筑工地(交通)
export const trafficConstructionSiteLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'trafficConstructionSite',
    titleKey: '工程名称',
    requestData: { type: '交通' }
  })
}

// 简易建筑
export const buildingLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'building',
    hideClassKey: '15',
    titleKey: 'building'
  })
}

// 危险建筑(农村危房)
export const ruralCrisisRoomLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'ruralCrisisRoom',
    titleKey: '建筑地址'
  })
}

// 户外立式广告牌
export const outBillboardLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'outBillboard',
    titleKey: '名称'
  })
}

// 抢险队
export const emergencySquadLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'emergencySquad',
    hideClassKey: ''
  })
}

// 救援队
export const rescueTeamLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'rescueTeam',
    hideClassKey: ''
  })
}

// 重点人员位置
export const liabilityPersonLayer = ({ layerOptions }) => {
  const layerKey = 'liabilityPerson'

  if (ordinaryInfo[layerKey] === undefined) {
    ordinaryInfo[layerKey] = (res) => {
      const layerName = `${layerKey}Layer`

      if (res.code === ERR_OK) {
        const features = Feature.createFeaturesIcon({
          lngKey: 'lng',
          latKey: 'lat',
          data: res.result,
          img: require(`./img/${layerKey}.png`)
        })

        const layer = Layer.createLayerIcon({ layerName, features })

        const overLayerArr = []

        res.result.map(item => {
          const lng = item.lng
          const lat = item.lat
          if (lng && lat) {
            let name = ''
            if (item.name1) {
              name = item.name1
            } else if (item.name2) {
              name = item.name2
            } else if (item.name3) {
              name = item.name3
            } else if (item.name4) {
              name = item.name4
            } else if (item.name5) {
              name = item.name5
            }

            if (name) {
              const htmlStr = `
                <div>
                  <span class="GykjMap-info-blue">${name}</span>
                </div>
              `

              const overLayer = Layer.createOverLayer({
                element: Common._createInfoBox(htmlStr, `GykjMap-${layerKey}`),
                position: [lng, lat]
              })
              overLayerArr.push(overLayer)
            }
          }
        })

        const ModalConstructor = Vue.extend(Modal[layerKey])

        const showModal = (options) => {
          if (ordinaryModal[layerKey] === undefined) {
            ordinaryModal[layerKey] = new ModalConstructor()
            ordinaryModal[layerKey].vm = ordinaryModal[layerKey].$mount()
            document.body.appendChild(ordinaryModal[layerKey].vm.$el)
          }

          ordinaryModal[layerKey].vm.$el.style.zIndex = modalZIndex += 1
          ordinaryModal[layerKey].showModal(options)
        }

        return {
          code: res.code,
          layerName,
          layer,
          overLayerArr,
          showModal
        }
      } else {
        return res
      }
    }
  }

  return Common._customData(layerOptions, {
    url: Url[`${layerKey}LayerUrl`],
    data: {},
    callback: ordinaryInfo[layerKey]
  })
}

// 三防专家实时位置
export const defenseExpertLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'defenseExpert',
    hideClassKey: ''
  })
}

// 村居
export const rusticateLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'rusticate',
    lngKey: 'longitude',
    latKey: 'latitude'
  })
}

// 避难所
export const refugeLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'refuge'
  })
}

// 物资仓库
export const emergencyLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'emergency'
  })
}

// 铁皮屋
export const ironhideHouseLayer = ({ layerOptions }) => {
  return arcgisIconLayer(layerOptions, {
    layerKey: 'ironhideHouse',
    mode: '铁皮屋',
    lngKey: '经度',
    latKey: '纬度'
  })
}

// 工棚
export const barrackLayer = ({ layerOptions }) => {
  return arcgisIconLayer(layerOptions, {
    layerKey: 'barrack',
    mode: '工棚',
    lngKey: '经度',
    latKey: '纬度'
  })
}

// 其他防风敏感建筑
export const otherBuildLayer = ({ layerOptions }) => {
  return arcgisIconLayer(layerOptions, {
    layerKey: 'otherBuild',
    mode: '其他防风敏感建筑',
    lngKey: '经度',
    latKey: '纬度'
  })
}

// 供水管网
export const supplyPipeLayer = ({ layerOptions }) => {
  return pipeLayer(layerOptions, {
    layerKey: 'supplyPipe',
    strokeColor: '#ff0000',
    strokeWidth: 3
  })
}

// 自来水厂
export const waterFactoryLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'waterFactory',
    titleKey: 'factory_name'
  })
}

// 供水设施
export const supplyDeviceLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'supplyDevice',
    lngKey: 'startlnt',
    latKey: 'startlat',
    titleKey: 'pipe_line_name',
    hideClassKey: '15'
  })
}

// 排水管
export const drainPipeLayer = ({ layerOptions }) => {
  return pipeLayer(layerOptions, {
    layerKey: 'drainPipe',
    strokeColor: '#7f00ff',
    strokeWidth: 3
  })
}

// 污水厂
export const dirtyFactoryLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'dirtyFactory',
    lngKey: 'lnt',
    titleKey: 'factory_name'
  })
}

// 排水设施
export const drainDeviceLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'drainDevice',
    lngKey: 'startlnt',
    latKey: 'startlat',
    titleKey: 'pipe_line_name',
    hideClassKey: '15'
  })
}

// 医院
export const hospitalLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'hospital',
    requestData: { type: '医院' }
  })
}

// 银行
export const bankLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'bank',
    requestData: { type: '银行' }
  })
}

// 客运站
export const busStationLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'busStation',
    requestData: { type: '客运站' }
  })
}

// 商场
export const shopLayer = ({ layerOptions }) => {
  return ordinaryLayer(layerOptions, {
    layerKey: 'shop',
    requestData: { type: '商场' }
  })
}

// 绘制工具图层
const drawStyles = (typeStyle) => {
  const {
    PointRadius,
    PointFillColor,
    LineStringStrokeColor,
    LineStringStrokeWidth,
    PolygonStrokeColor,
    PolygonStrokeLineDash,
    PolygonStrokeWidth,
    PolygonFillColor,
    CircleStrokeColor,
    CircleStrokeLineDash,
    CircleStrokeWidth,
    CircleFillColor
  } = typeStyle

  const styleObj = {
    'Point': [Style.createStyle({
      image: Style.createCircle({
        radius: PointRadius || 7,
        fill: Style.createFill({
          color: PointFillColor || 'black'
        })
      })
    })],
    'LineString': [Style.createStyle({
      stroke: Style.createStroke({
        color: LineStringStrokeColor || 'green',
        width: LineStringStrokeWidth || 10
      })
    })],
    'Polygon': [Style.createStyle({
      stroke: Style.createStroke({
        color: PolygonStrokeColor || 'blue',
        lineDash: PolygonStrokeLineDash || [0],
        width: PolygonStrokeWidth || 3
      }),
      fill: Style.createFill({
        color: PolygonFillColor || 'rgba(0, 0, 255, 0.1)'
      })
    })],
    'Circle': [Style.createStyle({
      stroke: Style.createStroke({
        color: CircleStrokeColor || 'red',
        lineDash: CircleStrokeLineDash || [0],
        width: CircleStrokeWidth || 2
      }),
      fill: Style.createFill({
        color: CircleFillColor || 'rgba(255,0,0,0.2)'
      })
    })]
  }
  return styleObj
}
export const drawUtilLayer = ({ layerOptions }) => {
  const {
    typeStyle = {},
    Map,
    onDrawStart = () => {},
    onDrawEnd = () => {},
    onModifySelect = () => {},
    onModifySelectChange = () => {}
  } = layerOptions

  let SelectFeature = {}
  const layerName = 'drawUtilLayer'

  const source = Source.createSourceVector({
    wrapX: false
  })
  const layer = Layer.createLayerVector({
    source,
    name: layerName,
    style (feature, resolution) {
      const styleObj = drawStyles(typeStyle)
      return styleObj[feature.getGeometry().getType()]
    }
  })

  const Modify = {
    init () {
      this.select = Interactions.createdInteractionSelect()
      Map.addInteraction(this.select)
      SelectFeature = this.select
      this.modify = Interactions.createdInteractionModify({
        features: this.select.getFeatures()
      })
      Map.addInteraction(this.modify)
      this.setEvents()
    },
    setEvents () {
      const selectedFeatures = this.select.getFeatures()
      this.select.on('select', (e) => {
        const feature = e.selected[0]
        const geometry = feature.getGeometry()
        const type = geometry.getType()
        const geoJson = Format.createGetFeatureGeoJson(feature)

        feature.un('change', () => {})
        feature.on('change', (e) => {
          const featureChild = e.target
          const geometryChild = featureChild.getGeometry()
          const typeChild = geometryChild.getType()
          const geoJsonChild = Format.createGetFeatureGeoJson(featureChild)

          const resChild = {
            feature: featureChild,
            geometry: geometryChild,
            type: typeChild,
            geoJson: geoJsonChild,
            onType: 'modifySelectChange'
          }

          if (type === 'Circle') {
            resChild.center = geometryChild.getCenter()
            resChild.radius = geometryChild.getRadius()
          } else {
            resChild.local = geometryChild.getCoordinates()
          }

          onModifySelectChange(resChild)
        })
        const res = {
          feature,
          geometry,
          type,
          geoJson,
          onType: 'modifySelect'
        }

        if (type === 'Circle') {
          res.center = geometry.getCenter()
          res.radius = geometry.getRadius()
        } else {
          res.local = geometry.getCoordinates()
        }

        onModifySelect(res)
      })
      this.select.on('change:active', () => {
        selectedFeatures.forEach(selectedFeatures.remove, selectedFeatures)
      })
    },
    setActive (options = {}) {
      const { active = false } = options

      this.select.setActive(active)
      this.modify.setActive(active)
    }
  }

  Modify.init()
  // console.log(Modify)
  const Draw = {
    init () {
      Map.addInteraction(this.Point)
      this.Point.setActive(false)
      Map.addInteraction(this.LineString)
      this.LineString.setActive(false)
      Map.addInteraction(this.Polygon)
      this.Polygon.setActive(false)
      Map.addInteraction(this.Circle)
      this.Circle.setActive(false)
      Map.addInteraction(this.Square)
      this.Square.setActive(false)
      Map.addInteraction(this.Box)
      this.Box.setActive(false)
    },
    Point: Interactions.createdInteractionDraw({
      source: layer.getSource(),
      type: 'Point'
    }),
    LineString: Interactions.createdInteractionDraw({
      source: layer.getSource(),
      type: 'LineString'
    }),
    Polygon: Interactions.createdInteractionDraw({
      source: layer.getSource(),
      type: 'Polygon'
    }),
    Circle: Interactions.createdInteractionDraw({
      source: layer.getSource(),
      type: 'Circle'
    }),
    Square: Interactions.createdInteractionDraw({
      source: layer.getSource(),
      type: 'Circle',
      geometryFunction: InteractionDraw.createRegularPolygon(4)
    }),
    Box: Interactions.createdInteractionDraw({
      source: layer.getSource(),
      type: 'LineString',
      maxPoints: 2,
      geometryFunction (coordinates, geometry) {
        if (!geometry) {
          geometry = Geom.createPolygon(null)
        }
        var start = coordinates[0]
        var end = coordinates[1]
        geometry.setCoordinates([
          [start, [start[0], end[1]], end, [end[0], start[1]], start]
        ])
        return geometry
      }
    }),
    getActive () {
      return this.activeType ? this[this.activeType].getActive() : false
    },
    setActive (options = {}) {
      const { active = false, type = 'Point' } = options

      if (active) {
        this.activeType && this[this.activeType].setActive(false)
        this[type].setActive(true)
        this.activeType = type
      } else {
        this.activeType && this[this.activeType].setActive(false)
        this.activeType = null
      }
    }
  }
  Draw.init()

  const removeDrawUtil = () => {
    Draw.setActive({ active: false })
    Modify.setActive({ active: false })
  }

  const addDraw = (options = {}) => {
    const { type } = options

    Draw.setActive({ active: true, type })
    Modify.setActive({ active: false })
  }

  const editDraw = (options = {}) => {
    Draw.setActive({ active: false })
    Modify.setActive({ active: true })
  }

  const deleteDraw = (options = {}) => {
    const selectFeatureArr = SelectFeature.getFeatures().getArray()
    selectFeatureArr.map(item => {
      layer.getSource().removeFeature(item)
    })

    Modify.setActive({ active: false })
    Modify.setActive({ active: true })
  }

  const deleteAllDraw = () => {
    Draw.setActive({ active: false })
    Modify.setActive({ active: false })

    layer.getSource().clear()
  }

  const getDrawLayerGeoJson = () => {
    return Format.createGetFeatureGeoJson(layer.getSource().getFeatures())
  }

  Draw.Point.on('drawstart', (e) => {
    const feature = e.feature
    const geometry = feature.getGeometry()
    const local = geometry.getCoordinates()

    onDrawStart({
      feature,
      geometry,
      local,
      lng: local[0],
      lat: local[1],
      type: 'Point',
      onType: 'drawstart'
    })
  })
  Draw.Point.on('drawend', (e) => {
    const feature = e.feature
    const geometry = feature.getGeometry()
    const local = geometry.getCoordinates()
    const geoJson = Format.createGetFeatureGeoJson(feature)

    onDrawEnd({
      feature,
      geometry,
      geoJson,
      local,
      lng: local[0],
      lat: local[1],
      type: 'Point',
      onType: 'drawend'
    })
  })

  Draw.LineString.on('drawstart', (e) => {
    const feature = e.feature
    const geometry = feature.getGeometry()
    const local = geometry.getCoordinates()

    onDrawStart({
      feature,
      geometry,
      localStart: local[0],
      type: 'LineString',
      onType: 'drawstart'
    })
  })
  Draw.LineString.on('drawend', (e) => {
    const feature = e.feature
    const geometry = feature.getGeometry()
    const localData = geometry.getCoordinates()
    const geoJson = Format.createGetFeatureGeoJson(feature)

    onDrawEnd({
      feature,
      geometry,
      geoJson,
      localData,
      type: 'LineString',
      onType: 'drawend'
    })
  })

  Draw.Polygon.on('drawstart', (e) => {
    const feature = e.feature
    const geometry = feature.getGeometry()
    const local = geometry.getCoordinates()

    onDrawStart({
      feature,
      geometry,
      localStart: local[0][0],
      type: 'Polygon',
      onType: 'drawstart'
    })
  })
  Draw.Polygon.on('drawend', (e) => {
    const feature = e.feature
    const geometry = feature.getGeometry()
    const localData = geometry.getCoordinates()
    const geoJson = Format.createGetFeatureGeoJson(feature)

    onDrawEnd({
      feature,
      geometry,
      geoJson,
      localData,
      type: 'Polygon',
      onType: 'drawend'
    })
  })

  Draw.Circle.on('drawstart', (e) => {
    const feature = e.feature
    const geometry = feature.getGeometry()
    const center = geometry.getCenter()

    onDrawStart({
      feature,
      geometry,
      center,
      type: 'Circle',
      onType: 'drawstart'
    })
  })
  Draw.Circle.on('drawend', (e) => {
    const feature = e.feature
    const geometry = feature.getGeometry()
    const center = geometry.getCenter()
    const radius = geometry.getRadius()
    const geoJson = Format.createGetFeatureGeoJson(feature)

    onDrawEnd({
      feature,
      geometry,
      geoJson,
      center,
      radius,
      type: 'Circle',
      onType: 'drawend'
    })
  })

  Draw.Square.on('drawstart', (e) => {
    const feature = e.feature
    const geometry = feature.getGeometry()
    const local = geometry.getCoordinates()

    onDrawStart({
      feature,
      geometry,
      localStart: local[0][0],
      type: 'Square',
      onType: 'drawstart'
    })
  })
  Draw.Square.on('drawend', (e) => {
    const feature = e.feature
    const geometry = feature.getGeometry()
    const local = geometry.getCoordinates()
    const geoJson = Format.createGetFeatureGeoJson(feature)

    onDrawEnd({
      feature,
      geometry,
      geoJson,
      local,
      type: 'Square',
      onType: 'drawend'
    })
  })

  Draw.Box.on('drawstart', (e) => {
    const feature = e.feature
    const geometry = feature.getGeometry()
    const local = geometry.getCoordinates()

    onDrawStart({
      feature,
      geometry,
      localStart: local[0][0],
      type: 'Box',
      onType: 'drawstart'
    })
  })
  Draw.Box.on('drawend', (e) => {
    const feature = e.feature
    const geometry = feature.getGeometry()
    const local = geometry.getCoordinates()
    const geoJson = Format.createGetFeatureGeoJson(feature)

    onDrawEnd({
      feature,
      geometry,
      geoJson,
      local,
      type: 'Box',
      onType: 'drawend'
    })
  })

  return {
    layerName,
    Draw,
    Modify,
    SelectFeature,
    layer,
    removeDrawUtil,
    addDraw,
    editDraw,
    deleteDraw,
    deleteAllDraw,
    getDrawLayerGeoJson
  }
}
